#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int fd;              // 文件描述符
int ret;             // 返回值
char gpio_path[100]; // GPIO路径
int len;             // 字符串长度
char file_path[100]; // 文件路径
char buf[2];         // 用于读取 GPIO 值的缓冲区

// 导出 GPIO 引脚
int gpio_export(char *argv)
{
    fd = open("/sys/class/gpio/export", O_WRONLY); // 打开 export 文件
    if (fd < 0)
    {
        printf("open /sys/class/gpio/export error\n"); // 打开文件失败
        return -1;
    }
    len = strlen(argv);         // 获取参数字符串的长度
    ret = write(fd, argv, len); // 将参数字符串写入文件，导出 GPIO 引脚
    if (ret < 0)
    {
        printf("write /sys/class/gpio/export error\n"); // 写入文件失败
        return -2;
    }
    close(fd); // 关闭文件
}

// 取消导出 GPIO 引脚
int gpio_unexport(char *argv)
{
    fd = open("/sys/class/gpio/unexport", O_WRONLY); // 打开 unexport 文件
    if (fd < 0)
    {
        printf("open /sys/class/gpio/unexport error\n"); // 打开文件失败
        return -1;
    }
    len = strlen(argv);         // 获取参数字符串的长度
    ret = write(fd, argv, len); // 将参数字符串写入文件，取消导出 GPIO 引脚
    if (ret < 0)
    {
        printf("write /sys/class/gpio/unexport error\n"); // 写入文件失败
        return -2;
    }
    close(fd); // 关闭文件
}

// 控制 GPIO 引脚的属性
int gpio_ctrl(char *arg, char *val)
{
    sprintf(file_path, "%s/%s", gpio_path, arg); // 构建文件路径，格式为 "gpio_path/arg"
    fd = open(file_path, O_WRONLY);              // 打开文件
    if (fd < 0)
    {
        printf("open file_path error\n"); // 打开文件失败
        return -1;
    }
    len = strlen(val);         // 获取参数字符串的长度
    ret = write(fd, val, len); // 将参数字符串写入文件，控制 GPIO 引脚的属性
    if (ret < 0)
    {
        printf("write file_path error\n"); // 写入文件失败
        return -2;
    }
    close(fd); // 关闭文件
}

// 读取 GPIO 引脚的值
int gpio_read_value(char *arg)
{
    sprintf(file_path, "%s/%s", gpio_path, arg); // 构建文件路径，格式为 "gpio_path/arg"
    fd = open(file_path, O_RDONLY);              // 打开文件
    if (fd < 0)
    {
        printf("open file_path error\n"); // 打开文件失败
        return -1;
    }
    ret = read(fd, buf, 1); // 读取文件内容到缓冲区
    if (!strcmp(buf, "1"))
    {
        printf("The value is high\n"); // GPIO 引脚值为高电平
        return 1;
    }
    else if (!strcmp(buf, "0"))
    {
        printf("The value is low\n"); // GPIO 引脚值为低电平
        return 0;
    }

    close(fd); // 关闭文件
    return -1;
}

int main(int argc, char *argv[]) // 主函数
{
    int value;
    sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]); // 构建 GPIO 路径，格式为 "/sys/class/gpio/gpio引脚号"
    if (access(gpio_path, F_OK))                           // 检查 GPIO 路径是否存在
    {
        gpio_export(argv[1]); // 不存在则导出 GPIO 引脚
    }
    else
    {
        gpio_unexport(argv[1]); // 存在则取消导出 GPIO 引脚
    }

    gpio_ctrl("direction", "in"); // 配置 GPIO 为输入模式

    value = gpio_read_value("value");   // 读取 GPIO 引脚的值
    printf("The value is %d\n", value); // 打印读取的 GPIO 引脚的值
    gpio_unexport(argv[1]);             // 最后取消导出 GPIO 引脚

    return 0; // 返回 0 表示程序正常退出
}